#! /usr/local/bin/python
#-*- coding: utf-8 -*-

"""Interface graphique pour le chargement et la suppression des parties.

_Fenêtre Toplevel modale_
"""

"""
Minesweeper 3K. Original implementation of the classic game of mines
for Python 3.
Copyright (C) 2010  Cedric Bonhomme

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.

Minesweeper 3K  Copyright (C) 2010  Cedric Bonhomme
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
"""

__author__ = "Jerome Hussenet, Cedric Bonhomme"
__date__ = "$Date: 2010/02/27 $"
__copyright__ = "Copyright (c) 2010 Jerome Hussenet, Copyright (c) 2010 Cedric Bonhomme"
__license__ = "GPL 3"

from tkinter import *
import tkinter.messagebox

import sauvegarde

class ChargementGui(object):
    """Interface graphique pour le chargement des parties.

    Permet de chosir une partie sauvegardée afin de la restaurer.
    Permet également de supprimer une partie.
    """
    def __init__(self, parent):
        """Initialisation de l'interface graphique.
        """
        self.parent = parent

        self.frame = Toplevel()
        self.frame.title(_('Restauration de parties'))
        self.frame.resizable(height = False, width = False)

        self.listeSauvegarde = []
        #self.save = sauvegarde.Sauvegarde()

        self.message1 = Label(self.frame)

        self.initInterface() # chargement de la ListBox

        # Menu popup pour la suppression
        self.popup = Menu(self.frame, tearoff = 0)
        self.popup.add_command(label=_("Supprimer cette sauvegarde"), command = self.supprime)

        ## fixe le focus sur la fenêtre (obligatoire pour Windows)
        self.frame.focus_set()
        ## Force les évènements à aller sur cette fenêtre
        self.frame.grab_set()
        ## Pour que la fenêtre reste au-dessus de sa fenêtre parente
        self.frame.transient(parent.master)
        ## Affiche la fenêtre et attend sa fermeture
        self.frame.wait_window(self.frame)

    def initInterface(self):
        """Charge les sauvegardes dans la ListBox.

        Lit le fichier XML de sauvegarde pour charger la ListBox.
        """
        self.save = sauvegarde.Sauvegarde()
        self.listeSauvegarde =  self.save.chargement(tout = True)
        if self.listeSauvegarde:  # si il existe des parties sauvegardées
            self.message = Label(self.frame, text = _("Liste des parties sauvegardées :"))
            self.message.grid(row=0, column = 0, columnspan = 2, pady = 10)

            self.afficheListeBox()
            self.rempliListeBox()

            self.message1 = Label(self.frame, \
                text = _('\nChoisissez une partie,\npuis double-cliquez dessus.\n'))
            self.message1.grid(row=2, columnspan = 2, padx = 50, pady = 10)
        else:
            self.afficheLabels()

    def afficheListeBox(self):
        """Affiche simplement une listbox.

        Cette listbox contient la liste des parties sauvegardée.
        """
        #ListBox contenant les sauvegardes.
        self.listboxScroll = Scrollbar(self.frame, orient = VERTICAL)
        self.listboxScroll.grid(row = 1, column = 2, sticky = W)
        self.listbox = Listbox(self.frame, yscrollcommand = self.listboxScroll.set, height = 1, width = 60)
        self.listbox.grid(row = 1, column = 1, sticky = W + E)
        self.listboxScroll['command'] = self.listbox.yview

        self.listbox.bind("<Double-Button-1>", self.panelCode)
        self.listbox.bind("<Button-3>", self.popup)

    def rempliListeBox(self):
        """Charge la listbox.

        Parse le fichier XML via le module sauvegarde
        pour charger la listbox.
        """
        for sauv in self.listeSauvegarde:
                if not self.save.estProtege(sauv[0]):
                    ligne = sauv[0] + _(", niveau ") + \
                        sauv[2] + ". " + str(sauv[1]) + \
                        _(" secondes ecoulees.")
                else:
                    ligne = sauv[0] + ", niveau " + \
                        sauv[2] + ". " + str(sauv[1]) + \
                        _(" secondes ecoulees. Verrouillee")
                self.listbox.insert(END, ligne)

    def afficheLabels(self):
        """Affiche un label

        Uniquement si aucune partie n'est sauvegardée.
        """
        self.message1.grid(row=2, columnspan = 2, padx = 50, pady = 10)
        self.message1.configure(text = _('Encore aucune sauvegarde.'))
        Button(self.frame, text = _("OK"), command = self.frame.destroy).grid(row = 3, columnspan = 2)

    def panelCode(self, event):
        """Panel de saisie du Code.

        Le panel s'affiche uniquement pour les parties vérouillées.
        """
        def execute(): # récupère le mot de passe saisi.
            try:
                passwd = code.get()
                msg.destroy()
                self.charge(date, passwd)
            except ValueError:
                tkinter.messagebox.showerror(_('Erreur'), _("Entrée saisie incorrecte."))
                msg.destroy()

        i = self.listbox.curselection()
        date = self.listeSauvegarde[int(i[0])][0]

        if self.save.estProtege(date) == True: # si la partie est protégée par mot de passe
            msg = Toplevel(self.frame)
            msg.title(_('Restaurer une partie'))
            msg.resizable(height = False, width = False)

            Label(msg, text=_('Restauration de la partie du ')+ date +_('.')) \
                .grid(row = 0, column = 0, padx = 50, pady = 10)

            Label(msg, text=_('Entrez votre mot de passe :')) \
                .grid(row = 1, column = 0, padx = 50, pady = 5)
            code = Entry(msg)
            code.configure(show = '*')
            code.grid(row = 2, column = 0, padx = 50, pady = 5)
            code.focus_set()

            Button(msg, text=_("OK"), \
                command = execute).grid(row = 3, columnspan = 2, padx = 50, pady = 5)

            ## fixe le focus sur la fenêtre (obligatoire pour Windows)
            msg.focus_set()
            ## Force les évènements à aller sur cette fenêtre
            #msg.grab_set()
            ## Pour que la fenêtre reste au-dessus de sa fenêtre parente
            msg.transient(self.frame)
            ## Affiche la fenêtre et attend sa fermeture
            msg.wait_window(msg)
        else:
            self.charge(date, "")


    def charge(self, date, passwd):
        """Charge la partie si le code est bon.

        Si un code est necessaire et s'il est bon,
        revoie les informations utiles à la restauration de la partie.
        (temps, nombre de mines, hauteur, largeur, etc.)
        """
        resultat = self.save.chargement(date = date, code = passwd)
        if resultat != []:
            (date, temps, niveau, mines, largeur, hauteur, le, lm) = resultat[0]
            self.parent.rechargerPartie(temps, niveau, int(largeur), \
                int(hauteur), int(mines), le, lm)
            self.frame.destroy()
            return
        else:
            tkinter.messagebox.showerror(_('Erreur'), _("Mauvais mot de passe."))

    def popup(self, event):
        """Ouvre un menu popup aux coordonnées de la souris.

        Appelé lors du double-clic droit sur la listbox.
        """
        try:
            self.popup.tk_popup(event.x_root, event.y_root)
        finally:
            # make sure to release the grab (Tk 8.0a1 only)
            #self.popup.grab_release()
            pass

    def supprime(self):
        """Suprime une partie.

        Supprime la balise XML de la partie ainsi que sa ligne
        correspondante dans la listbox.
        """
        i = self.listbox.curselection()
        if i: # si une partie est sélectionnée on la supprime
            date = str(self.listeSauvegarde[int(i[0])][0])
            #del self.save
            #self.save = sauvegarde.Sauvegarde()
            self.save.supprime(date)
            self.save.write()
            self.save = sauvegarde.Sauvegarde()
            self.listeSauvegarde =  self.save.chargement(tout = True)

            self.listbox.delete(int(i[0]), int(i[0])) # mise à jour de l'interface
            if self.listbox.size() == 0: # si plus de sauvegardes
                self.listbox.destroy() # on met à jour la listebox
                self.listboxScroll.destroy()
                self.message.destroy()
                self.afficheLabels()
            else:
                self.listbox.delete(0, END)
                self.rempliListeBox()
        else:
            tkinter.messagebox.showerror(_('Erreur'), _('Sélectionnez une partie.'))

if __name__ == '__main__':
    # Point d'entrée en exécution
    sauv = ChargementGui()